#include "monitor.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <dirent.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <iostream>
#include <Fl/fl_ask.h>
#define PATH_MAX 4096
#define LOGIN_SERVER "/home/elektrogame/elektroserver/trunk/login-server"
#define CHAR_SERVER "/home/elektrogame/elektroserver/trunk/char-server"
#define MAP_SERVER "/home/elektrogame/elektroserver/trunk/map-server"
Fl_Double_Window *w;
int ackapa = 0;
bool lackapa=false;
bool cackapa=false;
bool mackapa=false;
extern Fl_Check_Button *autostart;
extern Fl_Button *sunucuBaslat;
extern Fl_Light_Button *loginBaslat;
extern Fl_Light_Button *charBaslat;
extern Fl_Light_Button *mapBaslat;
extern Fl_Output *out_ip;
extern Fl_Progress *progressbar;


void stop_process();
pid_t pid_login;
pid_t pid_char;
pid_t pid_map;
pid_t start_process(char *exec) {

    pid_t pid;
    pid = fork();
    pid_t childPID ;
    if (pid == 0) {
	if (!(fork())) {
	    execl(exec,exec,NULL);
	    exit(0);
	}
	exit(0);
    }
    wait(0);

    //std::cout<<pid;
//out_ip.value(pid);

//  if ( childPID == -1 )
//  {
//    printf( "failed to fork child\n" );
//    _exit( 1 );
//  }
//  else if ( childPID == 0 )
//  {
//    execv( exec, NULL);
//  }
    return pid;
}
void ackapaLogin_CB(Fl_Widget *p)
{
    kill( pid_map, SIGHUP);
}

void ackapa_CB(Fl_Widget *p)
{
    Fl_Light_Button *gecici=(Fl_Light_Button *)p;
    //if(gecici==loginBaslat)
}

void sunucuBaslat_CB(Fl_Widget *p)
{
    if (ackapa ==0)
    {
        pid_login = start_process(LOGIN_SERVER);
        progressbar->position(loginBaslat->x(),loginBaslat->y());
        progressbar->show();
        progressbar->maximum(100);
        progressbar->minimum(0);
        for ( int t=1; t<=100; t++ ) {
            progressbar->value(t);       // update progress bar
            Fl::check();                    // give fltk some cpu to update the screen
            usleep(10000);                   // 'your stuff' that's compute intensive
        }
        progressbar->hide();
        loginBaslat->value(1);
        pid_char= start_process(CHAR_SERVER);
        progressbar->position(charBaslat->x(),charBaslat->y());
        progressbar->show();
        for ( int t=1; t<=100; t++ ) {
            progressbar->value(t);       // update progress bar
            Fl::check();                    // give fltk some cpu to update the screen
            usleep(10000);                   // 'your stuff' that's compute intensive
        }
        progressbar->hide();
        charBaslat->value(1);
         pid_map = start_process(MAP_SERVER);
        ackapa = 1;
        progressbar->position(mapBaslat->x(),mapBaslat->y());
        progressbar->show();
        for ( int t=1; t<=100; t++ ) {
            progressbar->value(t);       // update progress bar
            Fl::check();                    // give fltk some cpu to update the screen
            usleep(10000);                   // 'your stuff' that's compute intensive
        }
        sunucuBaslat->label("Sunucu Kapat");
        progressbar->hide();
        mapBaslat->value(1);
        lackapa=true;
        cackapa=true;
        mackapa=true;
    }
    else
    {
        stop_process();
        ackapa = 0;
        sunucuBaslat->label("Sunucu Baslat");
        lackapa=false;
        cackapa=false;
        mackapa=false;
    }

}


void stop_process() {
    system("killall -9 map-server");
    system("killall -9 login-server");
    system("killall -9 char-server");
    mapBaslat->value(0);
    charBaslat->value(0);
    loginBaslat->value(0);
    lackapa = false;
    cackapa = false;
    mackapa = false;
}
void tekStopProcess(char *name)
{
    std::string gecici;
    gecici="killall -9 ";
    gecici+=name;
    system(gecici.c_str());
}
void fresh(void *userdata)
{
    char pathbuf[PATH_MAX];
    struct dirent *procdirp;
    int proc_login = 0;
	int proc_map = 0;
	int proc_char = 0;
	struct tm *tmp;
    char timestamp[256];
    time_t t;
    char link[PATH_MAX];
    size_t l_size;
	DIR *procdir;

	if ( (procdir = opendir("/proc")) == NULL) {
	    fprintf(stderr,"ERROR: Cannot open /proc filesystem\n");
	    //return(255);
	    exit(0);
	}
	while ( (procdirp = readdir(procdir)) != NULL ) {
	    if ( strtok(procdirp->d_name, "0123456789") == NULL ) {
		sprintf(pathbuf, "%s%s%s", "/proc/", procdirp->d_name, "/exe");
		l_size = readlink(pathbuf, link, PATH_MAX);
		if (l_size != -1) {
		    link[l_size] = '\0';
		    if (!strcmp(link,LOGIN_SERVER)) {
			    proc_login = 1;
			    pid_login = (unsigned int) procdirp->d_name;
		    }
		    if (!strcmp(link,CHAR_SERVER)) {
			    proc_char = 1;
			    pid_char = (unsigned int) procdirp->d_name;
		    }
		    if (!strcmp(link,MAP_SERVER)) {
			    proc_map = 1;
			    pid_map = (unsigned int) procdirp->d_name;
		    }
		}
	    }
	}
	printf("Denemeasdfsdfas\n\n");
	closedir(procdir);

	/*if (!(log = fopen (logfile,"a"))) {
	    log = fopen("/tmp/monitor.log","a");
	}*/
	loginBaslat->value(proc_login);
	charBaslat->value(proc_char);
	mapBaslat->value(proc_map);
	t = time(NULL);
	tmp = localtime(&t);
	strftime(timestamp, sizeof(timestamp),"%F %X",tmp);
	if (proc_login == 0 &&  lackapa==true) {
	    //fprintf (log,"[%d][%s] NOTICE: Login server is dead - restarting\n",getpid(),timestamp);
	    loginBaslat->value(0);
	    start_process(LOGIN_SERVER);
	    sleep(2);
	}
	if (proc_char == 0 && cackapa==true) {
	    //fprintf (log,"[%d][%s] NOTICE: Char server is dead - restarting\n",getpid(),timestamp);
	    charBaslat->value(0);
	    start_process(CHAR_SERVER);
	    sleep(2);
	}
	if (proc_map == 0 && mackapa==true) {
	    //fprintf (log,"[%d][%s] NOTICE: Map server is dead - restarting\n",getpid(),timestamp);
	    mapBaslat->value(0);
	    start_process(MAP_SERVER);
	    sleep(2);
	}
	//fclose(log);
	//sleep(interval);
	Fl::repeat_timeout(5,fresh);
}
void windowOnClose_CB(Fl_Widget *p)
{
    //Hocam yaptım onclose olayını :)
    Fl::remove_timeout(fresh);
    system("killall -9 map-server");
    system("killall -9 char-server");
    system("killall -9 login-server");
    exit(0);
}
void tekAcKapa(Fl_Widget *p,void *userdata)
{
    Fl_Light_Button *gecici=dynamic_cast<Fl_Light_Button *>(p);
    if(strcmp(gecici->label(),"Login")==0)
    {
        if(lackapa==false)
        {
            start_process(LOGIN_SERVER);
            gecici->value(1);
            lackapa=true;
        }
        else
        {
            tekStopProcess("login-server");
            gecici->value(0);
            lackapa=false;
        }
    }
    else if(strcmp(gecici->label(),"Char")==0)
    {
        if(cackapa==false)
        {
            start_process(CHAR_SERVER);
            gecici->value(1);
            cackapa=true;
        }
        else
        {
            tekStopProcess("char-server");
            gecici->value(0);
            cackapa=false;
        }
    }
    else if(strcmp(gecici->label(),"Map")==0)
    {
        if(mackapa==false)
        {
            start_process(MAP_SERVER);
            gecici->value(1);
            mackapa=true;
        }
        else
        {
            tekStopProcess("map-server");
            gecici->value(0);
            mackapa=false;
            printf("Deneme");
        }
    }
}
void autoStart(Fl_Widget *p,void *userdata)
{
    Fl_Check_Button *gecici=dynamic_cast<Fl_Check_Button *>(p);
    if(gecici->value()==1)
    {
        Fl::add_timeout(5,fresh);
        loginBaslat->deactivate();
        charBaslat->deactivate();
        mapBaslat->deactivate();
    }
    else
    {
        Fl::remove_timeout(fresh);
        loginBaslat->activate();
        charBaslat->activate();
        mapBaslat->activate();
    }
}
int main()
{
    chdir("/home/elektrogame/elektroserver/trunk");
    w=make_window();
    sunucuBaslat->callback(sunucuBaslat_CB);
    autostart->callback(autoStart);
    loginBaslat->callback(tekAcKapa);
    charBaslat->callback(tekAcKapa);
    mapBaslat->callback(tekAcKapa);
    w->callback(windowOnClose_CB);
    w->show();
    char *y = new char();
    sprintf(y,"pid:%d",getpid());
    out_ip->value(y);

    return Fl::run();
}
